// Copyright (C) 2009  Lex Li
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Windows.Forms;
using System.Xml;

using Lextm.M8Pack.ThemeBuilder.Properties;
using WeifenLuo.WinFormsUI.Docking;

namespace Lextm.M8Pack.ThemeBuilder
{
    internal class MainScreenBuilder
    {
        private readonly IList<MainScreen> _screens = new List<MainScreen>();
        MainScreen _current;
        int _index = 1;
        private readonly IDictionary<string, IconInfo> _table;
        private readonly DockPanel _panel;

        public void Show()
        {
            for (int i = _screens.Count - 1; i >= 0; i--)
            {
                _screens[i].Show(_panel, DockState.Document);
            }
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")]
        public MainScreenBuilder(DockPanel panel)
        {
            _table = new Dictionary<string, IconInfo>();
            const string defaultFile = "icons.xml";
            const string settingLocaleFileMask = "icons.{0}.xml";
            string localizedFile = string.Format(
                CultureInfo.InvariantCulture,
                settingLocaleFileMask,
                CultureInfo.CurrentUICulture.Name);
            string settingFile;
            if (!File.Exists(localizedFile))
            {
                if (!File.Exists(defaultFile))
                {
                    return;
                }
                else
                {
                    settingFile = defaultFile;
                }
            }
            else
            {
                settingFile = localizedFile;
            }

            using (XmlTextReader reader = new XmlTextReader(settingFile))
            {
                try
                {
                    while (reader.Read())
                    {
                        switch (reader.NodeType)
                        {
                            case XmlNodeType.Element:
                                {
                                    if (reader.Name == "add")
                                    {
                                        string name = reader.GetAttribute("name");
                                        string displayName = reader.GetAttribute("displayName");

                                        _table.Add(name.ToUpper(), new IconInfo(name, displayName));
                                    }

                                    break;
                                }

                            default:
                                break;
                        }
                    }
                }
                finally
                {
                    reader.Close();
                }
            }
            _panel = panel;
        }

        public Theme Theme
        {
            set
            {
                DropCurrentScreens();
                if (value != null)
                {
                    CreateNewScreens(value);
                }
            }
        }

        private void CreateNewScreens(Theme theme)
        {
            foreach (var icon in theme.Icons)
            {
                AppendIcon(theme, icon);
            }
        }

        private void AppendIcon(Theme theme, KeyValuePair<string, string> icon)
        {
            if (_current == null || _current.Full)
            {
                _current = new MainScreen(theme, _index);
                _current.TabText += _index;
                _index++;
                _screens.Add(_current);
            }

            _current.AddIcon(icon, GetDisplayName(icon.Key.ToUpper()));
        }

        private string GetDisplayName(string name)
        {
            if (_table.ContainsKey(name))
            {
                return _table[name].DisplayName;
            }

            return name;
        }

        private void DropCurrentScreens()
        {
            foreach (MainScreen screen in _screens)
            {
                screen.Close();
            }

            _screens.Clear();
            _current = null;
            _index = 1;
        }

        internal Bitmap GetPreview()
        {
            return _screens[0].GetPreview();
        }

        internal void AddIcon(Theme theme)
        {
            using (FormIconName form = new FormIconName())
            {
                if (form.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                if (theme.Icons.ContainsKey(form.NewIcon.Key))
                {
                    return;
                }

                using (Image image = Helper.LoadImage(form.FileName))
                {
                    if (image.Width < 90 || image.Height < 90)
                    {
                        MessageBox.Show(Resources.PngSizeWarning);
                        return;
                    }

                    theme.ReplaceIcon(form.NewIcon.Key, form.FileName);
                }

                // TODO: work on display name.
                AppendIcon(theme, form.NewIcon);
                Show();
            }
        }

        internal void RemoveIcon()
        {
            // TODO: add this.
        }

        public void ChangeFont(Font font)
        {
            foreach (MainScreen screen in _screens)
            {
                screen.ChangeFont(font);
            }
        }

        public void SwitchMode()
        {
            foreach (MainScreen screen in _screens)
            {
                screen.SwitchMode();
            }
        }
        
        private class IconInfo
        {
            public string TagName;
            public string DisplayName;
            
            public IconInfo(string tag, string display)
            {
                TagName = tag;
                DisplayName = display;
            }
        }
    }
}